// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`issue-815.js 1`] = `
/* @flow */
type T = A|B;
class U {};
declare var children: U;
(children: T|U);
class A {};
class B {};

type VirtualElement = Thunk|VirtualNode;
type Child = VirtualElement;
type Children = Array<Child>;


class Thunk {}
class VirtualNode {
  children: Child|Children;
  constructor(type, children/*:Children*/) {
    this.children = children.length === 1 ? children[0] :
      children;
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
type T = A | B;
class U {}
declare var children: U;
(children: T | U);
class A {}
class B {}

type VirtualElement = Thunk | VirtualNode;
type Child = VirtualElement;
type Children = Array<Child>;

class Thunk {}
class VirtualNode {
  children: Child | Children;
  constructor(type, children /*: Children */) {
    this.children = children.length === 1 ? children[0] : children;
  }
}

`;

exports[`issue-824.js 1`] = `
import { B, C } from "./issue-824-helper";

type K = B | C;

type I = {
  which(): number;
};

export default class A {
  static foo(p: K): bool {
    return false;
  }
  static bar(p: I & K): bool {
    return this.foo(p);
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import { B, C } from "./issue-824-helper";

type K = B | C;

type I = {
  which(): number
};

export default class A {
  static foo(p: K): boolean {
    return false;
  }
  static bar(p: I & K): boolean {
    return this.foo(p);
  }
}

`;

exports[`issue-824-helper.js 1`] = `
import A from "./issue-824";

export class B extends A {
  which(): number {
    return 1;
  }
}
export class C extends A {
  which(): number {
    return 2;
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import A from "./issue-824";

export class B extends A {
  which(): number {
    return 1;
  }
}
export class C extends A {
  which(): number {
    return 2;
  }
}

`;

exports[`issue-1349.js 1`] = `
/* @flow */

var bar: Array<{b: ?boolean, c: number} | {b: boolean}> = [
  {b: true, c: 123},
  {b: true}
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

var bar: Array<{ b: ?boolean, c: number } | { b: boolean }> = [
  { b: true, c: 123 },
  { b: true }
];

`;

exports[`issue-1371.js 1`] = `
function create(a: any): { type: 'B', data: number } | { type: 'A', data: string }
{
  return {
    type: 'A',
    data: a
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function create(
  a: any
): { type: "B", data: number } | { type: "A", data: string } {
  return {
    type: "A",
    data: a
  };
}

`;

exports[`issue-1455.js 1`] = `
/* @flow */
import type {Foobar} from "./issue-1455-helper"

function create(content: ?Foobar | String | Array<String>) {
}

function node(content: ?Foobar | String | Array<String>) {
  create(content)
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
import type { Foobar } from "./issue-1455-helper";

function create(content: ?Foobar | String | Array<String>) {}

function node(content: ?Foobar | String | Array<String>) {
  create(content);
}

`;

exports[`issue-1455-helper.js 1`] = `
/* @flow */

export class Foobar { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

export class Foobar {}

`;

exports[`issue-1462-i.js 1`] = `
type Common = {
};

type A = Common & {
  type: 'A',
  foo: number
};

type B = Common & {
  type: 'B',
  foo: Array<number>
}

type MyType = A | B;

function print(x: number) {
  console.log(x);
}

function printAll(val: MyType) {
  print(val.foo);  // <--- foo could be an array
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type Common = {};

type A = Common & {
  type: "A",
  foo: number
};

type B = Common & {
  type: "B",
  foo: Array<number>
};

type MyType = A | B;

function print(x: number) {
  console.log(x);
}

function printAll(val: MyType) {
  print(val.foo); // <--- foo could be an array
}

`;

exports[`issue-1462-ii.js 1`] = `
type Common = {
};

type A = {
  type: 'A',
  foo: number
} & Common;

type B = {
  type: 'B',
  foo: Array<number>
} & Common;

type MyType = A | B;


function print(x: number) {
  console.log(x);
}

function printAll(val: MyType) {
  if (val.type === 'A') {
    print(val.foo);
  } else {
    val.foo.forEach(print);
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type Common = {};

type A = {
  type: "A",
  foo: number
} & Common;

type B = {
  type: "B",
  foo: Array<number>
} & Common;

type MyType = A | B;

function print(x: number) {
  console.log(x);
}

function printAll(val: MyType) {
  if (val.type === "A") {
    print(val.foo);
  } else {
    val.foo.forEach(print);
  }
}

`;

exports[`issue-1664.js 1`] = `
/* @flow */

type DataBase = {
  id: string,
  name: string,
};

type UserData = DataBase & {
  kind: "user",
};

type SystemData = DataBase & {
  kind: "system",
}

type Data = UserData | SystemData;

const data: Data = {
  id: "",
  name: "",
  kind: "system",
}

if (data.kind === "system") {
  (data: SystemData);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

type DataBase = {
  id: string,
  name: string
};

type UserData = DataBase & {
  kind: "user"
};

type SystemData = DataBase & {
  kind: "system"
};

type Data = UserData | SystemData;

const data: Data = {
  id: "",
  name: "",
  kind: "system"
};

if (data.kind === "system") {
  (data: SystemData);
}

`;

exports[`issue-1759.js 1`] = `
// @flow

type X = ({a:true} & {b:string}) | ({a:false} & {c:string});
//type X = {a:true, b:string} | {a:false, c:string}; // this works.

function hello(x:X): string {
  if (x.a === true) return x.b; else return x.c;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
//type X = {a:true, b:string} | {a:false, c:string}; // this works.

function hello(x: X): string {
  if (x.a === true) return x.b;
  else return x.c;
}

`;

exports[`issue-2232.js 1`] = `
/* @flow */

declare type Entity<T> = {
  id: T,
  name: string
}

declare type StringEntity = Entity<string>


declare type Foo = StringEntity & {
  bars: Object,
  kind: 1
}
declare type EmptyFoo = StringEntity &  {
  bars: null,
  kind: 2
}

function test(f: Foo| EmptyFoo) {
  if (f.kind === 1) {
    (f: Foo)
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

declare type Entity<T> = {
  id: T,
  name: string
};

declare type StringEntity = Entity<string>;

declare type Foo = StringEntity & {
  bars: Object,
  kind: 1
};
declare type EmptyFoo = StringEntity & {
  bars: null,
  kind: 2
};

function test(f: Foo | EmptyFoo) {
  if (f.kind === 1) {
    (f: Foo);
  }
}

`;

exports[`test1.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////
// example with object types
//////////////////////////////

function obj(a: A1 | A2) {
  return a.x;
}

const obj_result = obj({ x: "" }); // currently an error! (expect it to be OK)

// Type definitions used above are defined below, but in an order that
// deliberately makes their full resolution as lazy as possible. The call above
// blocks until A1 is partially resolved. Since the argument partially matches
// A1, that branch is selected. Later, that branch errors, but other branches
// have been lost by then.

type A1 = { x: B1 };
type A2 = { x: B2 };

type B1 = number;
type B2 = string;

(obj_result: B1 | B2);

///////////////////////////////////////
// similar example with function types
///////////////////////////////////////

function fun(a: A3 | A4) {
  return a();
}

const fun_result = fun(() => "");

type A3 = () => B3;
type A4 = () => B4;

type B3 = number;
type B4 = string;

(fun_result: B3 | B4);

/////////////////////////////////////////////
// similar example with class instance types
/////////////////////////////////////////////

function inst(a: A5 | A6) { }

class B5 { }
class B6 { }
inst([new B6]);

type A5 = B5[];
type A6 = B6[];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////
// example with object types
//////////////////////////////

function obj(a: A1 | A2) {
  return a.x;
}

const obj_result = obj({ x: "" }); // currently an error! (expect it to be OK)

// Type definitions used above are defined below, but in an order that
// deliberately makes their full resolution as lazy as possible. The call above
// blocks until A1 is partially resolved. Since the argument partially matches
// A1, that branch is selected. Later, that branch errors, but other branches
// have been lost by then.

type A1 = { x: B1 };
type A2 = { x: B2 };

type B1 = number;
type B2 = string;

(obj_result: B1 | B2);

///////////////////////////////////////
// similar example with function types
///////////////////////////////////////

function fun(a: A3 | A4) {
  return a();
}

const fun_result = fun(() => "");

type A3 = () => B3;
type A4 = () => B4;

type B3 = number;
type B4 = string;

(fun_result: B3 | B4);

/////////////////////////////////////////////
// similar example with class instance types
/////////////////////////////////////////////

function inst(a: A5 | A6) {}

class B5 {}
class B6 {}
inst([new B6()]);

type A5 = B5[];
type A6 = B6[];

`;

exports[`test2.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////
// example with object types
//////////////////////////////

function obj(a: { x: number } | { x: string }) { }

obj(({ x: "" }: A1));

type A1 = { x: B1 };

type B1 = string;

///////////////////////////////////////
// similar example with function types
///////////////////////////////////////

function fun(a: (() => number) | (() => string)) { }

fun(((() => ""): A2));

type A2 = () => B2;

type B2 = string;

/////////////////////////////////////////////////////
// similar example with generic class instance types
/////////////////////////////////////////////////////

class C<X> { }

function inst(a: C<number> | C<string>) { }

inst((new C: A3));

type A3 = C<B3>;

type B3 = string;

/////////////////////////////////////////////
// similar example with generic type aliases
/////////////////////////////////////////////

function alias(a: T<number> | T<string>) { }
alias({ x: (x: V<B4>) => { } });

type T<X> = { x: U<X> }
type U<X> = (x: V<X>) => void;
type V<X> = X;

type B4 = string;

// class statics

function stat(a: { x: number } | { x: string }) { }

class D {
  static x: B5;
}

stat(D);

type B5 = string;

// tuples

function tup(a: [number,boolean] | [string,boolean]) { }

tup((["",false]: A6));

type A6 = [B6,boolean];
type B6 = string;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////
// example with object types
//////////////////////////////

function obj(a: { x: number } | { x: string }) {}

obj(({ x: "" }: A1));

type A1 = { x: B1 };

type B1 = string;

///////////////////////////////////////
// similar example with function types
///////////////////////////////////////

function fun(a: (() => number) | (() => string)) {}

fun((() => "": A2));

type A2 = () => B2;

type B2 = string;

/////////////////////////////////////////////////////
// similar example with generic class instance types
/////////////////////////////////////////////////////

class C<X> {}

function inst(a: C<number> | C<string>) {}

inst((new C(): A3));

type A3 = C<B3>;

type B3 = string;

/////////////////////////////////////////////
// similar example with generic type aliases
/////////////////////////////////////////////

function alias(a: T<number> | T<string>) {}
alias({ x: (x: V<B4>) => {} });

type T<X> = { x: U<X> };
type U<X> = (x: V<X>) => void;
type V<X> = X;

type B4 = string;

// class statics

function stat(a: { x: number } | { x: string }) {}

class D {
  static x: B5;
}

stat(D);

type B5 = string;

// tuples

function tup(a: [number, boolean] | [string, boolean]) {}

tup((["", false]: A6));

type A6 = [B6, boolean];
type B6 = string;

`;

exports[`test3.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => void) | ((x: string) => void)) { }

fun((((x) => {}): A1));

type A1 = (x: B1) => void;

type B1 = string;

////////////////////////////
// example with array types
////////////////////////////

function arr(a: number[] | string[]) { }

arr(([]: A2));

type A2 = B2[];

type B2 = string;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => void) | ((x: string) => void)) {}

fun((x => {}: A1));

type A1 = (x: B1) => void;

type B1 = string;

////////////////////////////
// example with array types
////////////////////////////

function arr(a: number[] | string[]) {}

arr(([]: A2));

type A2 = B2[];

type B2 = string;

`;

exports[`test4.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => void) | ((x: string) => void)) { }

const a1 = ((x) => {}: A1);
fun(a1);

function fun_call(x: string) { a1(x); }

type A1 = (x: B1) => void;

type B1 = string;

////////////////////////////
// example with array types
////////////////////////////

function arr(a: number[] | string[]) { }

const a2 = ([]: A2);
arr(a2);

function arr_set(x: string, i: number) { a2[i] = x; }
function arr_get(i: number): string { return a2[i]; }

type A2 = B2[];

type B2 = string;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => void) | ((x: string) => void)) {}

const a1 = (x => {}: A1);
fun(a1);

function fun_call(x: string) {
  a1(x);
}

type A1 = (x: B1) => void;

type B1 = string;

////////////////////////////
// example with array types
////////////////////////////

function arr(a: number[] | string[]) {}

const a2 = ([]: A2);
arr(a2);

function arr_set(x: string, i: number) {
  a2[i] = x;
}
function arr_get(i: number): string {
  return a2[i];
}

type A2 = B2[];

type B2 = string;

`;

exports[`test5.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => number) | ((x: string) => string)) { }

function a1(x) { return x; }
fun(a1);

function fun_call(x: string): string { return a1(x); }

/////////////////////////////
// example with array types
/////////////////////////////

function arr(a: number[] | string[]) { }

var a2 = [];
arr(a2);

function arr_set(x: string, i: number) { a2[i] = x; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

///////////////////////////////
// example with function types
///////////////////////////////

function fun(a: ((x: number) => number) | ((x: string) => string)) {}

function a1(x) {
  return x;
}
fun(a1);

function fun_call(x: string): string {
  return a1(x);
}

/////////////////////////////
// example with array types
/////////////////////////////

function arr(a: number[] | string[]) {}

var a2 = [];
arr(a2);

function arr_set(x: string, i: number) {
  a2[i] = x;
}

`;

exports[`test6.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////////////////
// example with generic class inheritance
//////////////////////////////////////////

function inst(a: E<B4>): C<number> | C<string> { return a; }

const mk_C = () => C;
const mk_D = () => D;
const mk_E = () => E;

type B4 = string;

const _D = mk_D();
class E<X> extends _D<X> { }

const _C = mk_C();
class D<X> extends _C<X> { }

class C<X> { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////////////////////////
// example with generic class inheritance
//////////////////////////////////////////

function inst(a: E<B4>): C<number> | C<string> {
  return a;
}

const mk_C = () => C;
const mk_D = () => D;
const mk_E = () => E;

type B4 = string;

const _D = mk_D();
class E<X> extends _D<X> {}

const _C = mk_C();
class D<X> extends _C<X> {}

class C<X> {}

`;

exports[`test7.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

////////////////////
// recursive types
////////////////////

function rec(x: F1 | F2) { }
rec({ x: 0 });

type F1 = G1;
type F2 = G2;
type G1 = { x: H1, y?: G1 };
type G2 = { x: H2, y?: G2 };
type H1 = string;
type H2 = number;

///////////////////////////////
// polymorphic recursive types
///////////////////////////////

function polyrec(x: PF<number> | PF<string>) { }
rec({ x: 0 });

type PF<X> = PG<X>;
type PG<X> = { x: X, y?: PG<X> };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

////////////////////
// recursive types
////////////////////

function rec(x: F1 | F2) {}
rec({ x: 0 });

type F1 = G1;
type F2 = G2;
type G1 = { x: H1, y?: G1 };
type G2 = { x: H2, y?: G2 };
type H1 = string;
type H2 = number;

///////////////////////////////
// polymorphic recursive types
///////////////////////////////

function polyrec(x: PF<number> | PF<string>) {}
rec({ x: 0 });

type PF<X> = PG<X>;
type PG<X> = { x: X, y?: PG<X> };

`;

exports[`test8.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////
// nested union types
//////////////////////

function rec(x: F1 | F2) { }
rec({ x: 0 });

type F1 = G1 | G1_;
type F2 = G2 | G2_;
type G1 = { x: H1 };
type G1_ = { x: H1_ };
type G2 = { x: H2 };
type G2_ = { x: H2_ };
type H1 = boolean;
type H1_ = string;
type H2 = boolean;
type H2_ = number;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

//////////////////////
// nested union types
//////////////////////

function rec(x: F1 | F2) {}
rec({ x: 0 });

type F1 = G1 | G1_;
type F2 = G2 | G2_;
type G1 = { x: H1 };
type G1_ = { x: H1_ };
type G2 = { x: H2 };
type G2_ = { x: H2_ };
type H1 = boolean;
type H1_ = string;
type H2 = boolean;
type H2_ = number;

`;

exports[`test9.js 1`] = `
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

////////////////
// interference
////////////////

function square(x? = 0) {
  return x * x;
}

function foo(f: ((_: ?number) => ?number) | (() => void)) { }
foo((x): number => square(x))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/**
 * Test that shows how the implementation of union types is broken
 */

////////////////
// interference
////////////////

function square(x? = 0) {
  return x * x;
}

function foo(f: ((_: ?number) => ?number) | (() => void)) {}
foo((x): number => square(x));

`;

exports[`test10.js 1`] = `
// @noflow

function id<X>(x: X): X { return x; }

/////////////////////////
// primitive annotations
/////////////////////////

function check_prim(_: number | string) { }

// ok
check_prim("");

// ...even when they "flow" in
check_prim(id(""));

//////////////////////////////
// class instance annotations
//////////////////////////////

class C { }
class D { }
function check_inst(_: C | D) { }

// ok
check_inst(new D);

// ...even when they "flow" in
check_inst(id(new C));

////////////////////////
// function annotations
////////////////////////

function check_fun(_: ((_: number) => number) | ((_: string) => string)) { }

// help!
check_fun((x) => x);

//////////////////////
// object annotations
//////////////////////

function check_obj(_: { x: number } | { x: string }) { }

// ok
check_obj({ x: "" });

// help!
check_obj({ x: id("") });

/////////////////////
// array annotations
/////////////////////

function check_arr(_: number[] | string[]) { }

// help! (unlike objects, array literals' element types are always open)
check_arr([""]);

// help!
check_arr([id("")]);

//////////////////////////////////////
// generic class instance annotations
//////////////////////////////////////

class P<X> { }
function check_poly_inst(_: P<number> | P<string>) { }

// help!
check_poly_inst(new P);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

function id<X>(x: X): X {
  return x;
}

/////////////////////////
// primitive annotations
/////////////////////////

function check_prim(_: number | string) {}

// ok
check_prim("");

// ...even when they "flow" in
check_prim(id(""));

//////////////////////////////
// class instance annotations
//////////////////////////////

class C {}
class D {}
function check_inst(_: C | D) {}

// ok
check_inst(new D());

// ...even when they "flow" in
check_inst(id(new C()));

////////////////////////
// function annotations
////////////////////////

function check_fun(_: ((_: number) => number) | ((_: string) => string)) {}

// help!
check_fun(x => x);

//////////////////////
// object annotations
//////////////////////

function check_obj(_: { x: number } | { x: string }) {}

// ok
check_obj({ x: "" });

// help!
check_obj({ x: id("") });

/////////////////////
// array annotations
/////////////////////

function check_arr(_: number[] | string[]) {}

// help! (unlike objects, array literals' element types are always open)
check_arr([""]);

// help!
check_arr([id("")]);

//////////////////////////////////////
// generic class instance annotations
//////////////////////////////////////

class P<X> {}
function check_poly_inst(_: P<number> | P<string>) {}

// help!
check_poly_inst(new P());

`;

exports[`test11.js 1`] = `
// @noflow

// disjoint unions

function length(list: List) {
  if (list.kind === "cons") return length(list.next) + 1;
  else return 0;
}


length({ kind: "nil" });
length({ kind: "cons" }); // missing \`next\`
length({ kind: "cons", next: { kind: "nil" } });
length({ kind: "empty" }); // \`kind\` not found

type List = Nil | Cons;
type Nil = { kind: "nil" };
type Cons = { kind: "cons", next: List };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// disjoint unions

function length(list: List) {
  if (list.kind === "cons") return length(list.next) + 1;
  else return 0;
}

length({ kind: "nil" });
length({ kind: "cons" }); // missing \`next\`
length({ kind: "cons", next: { kind: "nil" } });
length({ kind: "empty" }); // \`kind\` not found

type List = Nil | Cons;
type Nil = { kind: "nil" };
type Cons = { kind: "cons", next: List };

`;

exports[`test12.js 1`] = `
// @noflow

// polymorphic recursive types

type F<X> = { f: F<X>, x: X }
type G = { x: number }
type H = { x: string }

function rec(x: F<string>): G | H { return x; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// polymorphic recursive types

type F<X> = { f: F<X>, x: X };
type G = { x: number };
type H = { x: string };

function rec(x: F<string>): G | H {
  return x;
}

`;

exports[`test13.js 1`] = `
// @noflow

/* ensure there are no unintended side effects when trying branches */

({type: 'B', id: 'hi'}: {
  type: 'A';
  id: ?string;
} | {
  type: 'B';
  id: string;
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

/* ensure there are no unintended side effects when trying branches */

({ type: "B", id: "hi" }:
  | {
      type: "A",
      id: ?string
    }
  | {
      type: "B",
      id: string
    });

`;

exports[`test14.js 1`] = `
// @noflow

// annotations

declare class C<X> {
  get(): X;
}

function union(o: { x: string } | { x: number }) { }

function foo(c: C<number>) {
  union({ x: c.get() });
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// annotations

declare class C<X> {
  get(): X;
}

function union(o: { x: string } | { x: number }) {}

function foo(c: C<number>) {
  union({ x: c.get() });
}

`;

exports[`test15.js 1`] = `
// @noflow

// functions as objects

function foo<X>(target: EventTarget) {
  target.addEventListener('click', (e) => {});
}

declare class EventTarget {
  addEventListener(type: 'foo', listener: KeyboardEventHandler): void;
  addEventListener(type: string, listener: EventHandler): void;
}

declare class Event { }
declare class KeyboardEvent { }

type EventHandler = (event: Event) => mixed
type KeyboardEventHandler = (event: KeyboardEvent) => mixed

// example where globals are not yet resolved

function bar(x: (() => void) | { x: number }) { }

bar(() => { });
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// functions as objects

function foo<X>(target: EventTarget) {
  target.addEventListener("click", e => {});
}

declare class EventTarget {
  addEventListener(type: "foo", listener: KeyboardEventHandler): void;
  addEventListener(type: string, listener: EventHandler): void;
}

declare class Event {}
declare class KeyboardEvent {}

type EventHandler = (event: Event) => mixed;
type KeyboardEventHandler = (event: KeyboardEvent) => mixed;

// example where globals are not yet resolved

function bar(x: (() => void) | { x: number }) {}

bar(() => {});

`;

exports[`test16.js 1`] = `
// @noflow

// annotations

type T = number | (() => string);
type Foo = T | (() => bool);

type Bar = number | (() => string) | (() => bool);

function foo(x: Foo) { }
foo(() => qux());

function bar(x: Bar) { }
bar(() => qux());

var x = false;
function qux() { return x; }
x = "";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// annotations

type T = number | (() => string);
type Foo = T | (() => boolean);

type Bar = number | (() => string) | (() => boolean);

function foo(x: Foo) {}
foo(() => qux());

function bar(x: Bar) {}
bar(() => qux());

var x = false;
function qux() {
  return x;
}
x = "";

`;

exports[`test17.js 1`] = `
// @noflow

// Array#concat

[].concat([]);

([].concat([0,1])[1]: string)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// Array#concat

[].concat([]);

([].concat([0, 1])[1]: string);

`;

exports[`test18.js 1`] = `
// @noflow

// method overloads

declare class C {
  m(x: number): void;
  m(x: string): void;
}

function f() { return 0; }

new C().m(f());
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// method overloads

declare class C {
  m(x: number): void;
  m(x: string): void;
}

function f() {
  return 0;
}

new C().m(f());

`;

exports[`test19.js 1`] = `
// @noflow

// constructor overloads

function m<X>() {
  return new D();
}

declare class D {
  constructor(_: void): void;
  constructor(_: null): void;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// constructor overloads

function m<X>() {
  return new D();
}

declare class D {
  constructor(_: void): void;
  constructor(_: null): void;
}

`;

exports[`test20.js 1`] = `
// @noflow

// Array#reduce

[0,1].reduce((x,y,i) => y);

["a", "b"].reduce(
  (regex, representation, index) => {
    return regex + (index ? '|' : '') + '(' + representation + ')';
  },
  '',
);

[""].reduce((acc,str) => acc * str.length);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// Array#reduce

[0, 1].reduce((x, y, i) => y);

["a", "b"].reduce((regex, representation, index) => {
  return regex + (index ? "|" : "") + "(" + representation + ")";
}, "");

[""].reduce((acc, str) => acc * str.length);

`;

exports[`test21.js 1`] = `
// @noflow

// annotations for disjoint unions

type T =
  | { type: "FOO", x: number }
  | { type: "BAR", x: string }

({ type: (bar(): "BAR"), x: str() }: T);

({ type: bar(), x: str() }: T);

({ type: bar(), x: (str(): string) }: T);

function bar() {
  return "BAR";
}

function str() {
  return "hello";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// annotations for disjoint unions

type T = { type: "FOO", x: number } | { type: "BAR", x: string };

({ type: (bar(): "BAR"), x: str() }: T);

({ type: bar(), x: str() }: T);

({ type: bar(), x: (str(): string) }: T);

function bar() {
  return "BAR";
}

function str() {
  return "hello";
}

`;

exports[`test22.js 1`] = `
// @noflow

// refinement of disjoint unions

type Empty = { }

type Success = {
  type: 'SUCCESS';
  result: string;
};

type Error = {
  type: 'ERROR';
} & Empty;

export type T = Success | Error;

function foo(x: T) {
  if (x.type === 'SUCCESS') return x.result;
  else return x.result;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// refinement of disjoint unions

type Empty = {};

type Success = {
  type: "SUCCESS",
  result: string
};

type Error = {
  type: "ERROR"
} & Empty;

export type T = Success | Error;

function foo(x: T) {
  if (x.type === "SUCCESS") return x.result;
  else return x.result;
}

`;

exports[`test23.js 1`] = `
// @noflow

// nested intersections (see also lib/test23_lib.js)

type NestedObj = { } & { dummy: SomeLibClass };

type Obj = NestedObj & { x: string };

function foo(obj: Obj) {
  obj.x; // should be OK
  obj.x; // should also be OK (the check above shouldn't affect anything)
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// nested intersections (see also lib/test23_lib.js)

type NestedObj = {} & { dummy: SomeLibClass };

type Obj = NestedObj & { x: string };

function foo(obj: Obj) {
  obj.x; // should be OK
  obj.x; // should also be OK (the check above shouldn't affect anything)
}

`;

exports[`test24.js 1`] = `
// @noflow

// scaling test for full type resolution

declare class C {
  addListener(event: string, listener: Function): C;
  emit(event: string, ...args:Array<any>): boolean;
  listeners(event: string): Array<Function>;
  listenerCount(event: string): number;
  on(event: string, listener: Function): C;
  once(event: string, listener: Function): C;
  removeAllListeners(event?: string): C;
  removeListener(event: string, listener: Function): C;
  setMaxListeners(n: number): void;
}

declare class D extends C {
  listen(port: number, hostname?: string, backlog?: number, callback?: Function): D;
  listen(path: string, callback?: Function): D;
  listen(handle: Object, callback?: Function): D;
  close(callback?: Function): D;
  address(): number;
  connections: number;
  maxConnections: number;
  getConnections(callback: Function): void;
  ref():  D;
  unref():  D;
}

(0: D | number);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// scaling test for full type resolution

declare class C {
  addListener(event: string, listener: Function): C;
  emit(event: string, ...args: Array<any>): boolean;
  listeners(event: string): Array<Function>;
  listenerCount(event: string): number;
  on(event: string, listener: Function): C;
  once(event: string, listener: Function): C;
  removeAllListeners(event?: string): C;
  removeListener(event: string, listener: Function): C;
  setMaxListeners(n: number): void;
}

declare class D extends C {
  listen(
    port: number,
    hostname?: string,
    backlog?: number,
    callback?: Function
  ): D;
  listen(path: string, callback?: Function): D;
  listen(handle: Object, callback?: Function): D;
  close(callback?: Function): D;
  address(): number;
  connections: number;
  maxConnections: number;
  getConnections(callback: Function): void;
  ref(): D;
  unref(): D;
}

(0: D | number);

`;

exports[`test25.js 1`] = `
// @noflow

// termination test (see also lib/test25_lib.js)

function foo(rows: Rows, set: Set<number>) {
  return rows.reduce_rows(
    (set, row) => row.reduce_row(
      (set, i) => set.add(i),
      set,
    ),
    set,
  );
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// termination test (see also lib/test25_lib.js)

function foo(rows: Rows, set: Set<number>) {
  return rows.reduce_rows(
    (set, row) => row.reduce_row((set, i) => set.add(i), set),
    set
  );
}

`;

exports[`test26.js 1`] = `
// @noflow

declare function foo(x: number): number;
declare function foo(x: string): string;

declare var x: number | string;

(foo(x): number | string);

type T = number | string;
declare var y: T;

(foo(y): T);

declare class Record {
  set(x: 'foo', y: number): void;
  set(x: 'bar', y: string): void;
}

new Record().set('foo', "42");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

declare function foo(x: number): number;
declare function foo(x: string): string;

declare var x: number | string;

(foo(x): number | string);

type T = number | string;
declare var y: T;

(foo(y): T);

declare class Record {
  set(x: "foo", y: number): void;
  set(x: "bar", y: string): void;
}

new Record().set("foo", "42");

`;

exports[`test27.js 1`] = `
// @noflow

type X = ({a:true} & {b:string}) | ({a:false} & {c:string});
//type X = {a:true, b:string} | {a:false, c:string}; // this works.

function hello1(x:X): string {
  if (x.a === true) return x.b; else return x.c;
}

function hello2(x:X): string {
  if (x.a === false) return x.c; else return x.b;
}

function hello3(x:X): string {
  if (x.a) { return x.b; } else { return x.c; }
}

function hello4(x:X): string {
  if (!x.a) { return x.c; } else { return x.b; }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
//type X = {a:true, b:string} | {a:false, c:string}; // this works.

function hello1(x: X): string {
  if (x.a === true) return x.b;
  else return x.c;
}

function hello2(x: X): string {
  if (x.a === false) return x.c;
  else return x.b;
}

function hello3(x: X): string {
  if (x.a) {
    return x.b;
  } else {
    return x.c;
  }
}

function hello4(x: X): string {
  if (!x.a) {
    return x.c;
  } else {
    return x.b;
  }
}

`;

exports[`test29.js 1`] = `
// @noflow

// Make sure caching doesn't cause a spurious successful match (e.g., when a
// failed match is tried again). This may happen, e.g., when checking
// polymorphic definitions, where the same code may be checked multiple times
// with different instantiations.

type Row = { x: string };

declare class D<T> {
  reduce(
    callbackfn: (previousValue: T, currentValue: T) => T,
    initialValue: void
  ): T;
  reduce<U>(
    callbackfn: (previousValue: U, currentValue: T) => U,
    initialValue: U
  ): U;
}

class C {
  foo(
    rows: D<Row>,
    minWidth: number,
  ): number {
    return rows.reduce(
      (length, row) => 0,
      minWidth,
    );
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// Make sure caching doesn't cause a spurious successful match (e.g., when a
// failed match is tried again). This may happen, e.g., when checking
// polymorphic definitions, where the same code may be checked multiple times
// with different instantiations.

type Row = { x: string };

declare class D<T> {
  reduce(
    callbackfn: (previousValue: T, currentValue: T) => T,
    initialValue: void
  ): T;
  reduce<U>(
    callbackfn: (previousValue: U, currentValue: T) => U,
    initialValue: U
  ): U;
}

class C {
  foo(rows: D<Row>, minWidth: number): number {
    return rows.reduce((length, row) => 0, minWidth);
  }
}

`;

exports[`test30.js 1`] = `
// @noflow

const Constants = require('./test30-helper');

type ActionType =
  | { type: 'foo', x: number }
  | { type: 'bar', x: number }

({ type: Constants.BAR, x: 0 }: ActionType);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

const Constants = require("./test30-helper");

type ActionType = { type: "foo", x: number } | { type: "bar", x: number };

({ type: Constants.BAR, x: 0 }: ActionType);

`;

exports[`test30-helper.js 1`] = `
// @noflow

module.exports = {
  FOO: 'foo',
  BAR: 'bar',
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

module.exports = {
  FOO: "foo",
  BAR: "bar"
};

`;

exports[`test31.js 1`] = `
// @noflow

// make sure tuples are type arguments (as used e.g. when viewing maps as
// key/value iterables) work

interface SomeIterator<T> { }

interface SomeIterable<T> {
  it(): SomeIterator<T>;
}

declare class SomeMap<K,V> {
  it(): SomeIterator<[K,V]>;
  set(k: K, v: V): void;
}

declare class ImmutableMap<K,V> { }

declare function convert<K,V>(iter: SomeIterable<[K,V]>): ImmutableMap<K,V>;

function foo(): ImmutableMap<string, boolean> {
  const countersGlobalMap = new SomeMap();
  countersGlobalMap.set("", false);
  return convert(countersGlobalMap);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow

// make sure tuples are type arguments (as used e.g. when viewing maps as
// key/value iterables) work

interface SomeIterator<T> {}

interface SomeIterable<T> {
  it(): SomeIterator<T>;
}

declare class SomeMap<K, V> {
  it(): SomeIterator<[K, V]>;
  set(k: K, v: V): void;
}

declare class ImmutableMap<K, V> {}

declare function convert<K, V>(iter: SomeIterable<[K, V]>): ImmutableMap<K, V>;

function foo(): ImmutableMap<string, boolean> {
  const countersGlobalMap = new SomeMap();
  countersGlobalMap.set("", false);
  return convert(countersGlobalMap);
}

`;

exports[`test32.js 1`] = `
// @flow

// make sure that full resolution jobs don't cache improperly to signal success
// when they have failed earlier

function foo(value: Indirect<string> | number): Indirect<string> | number {
  const castedValue: number = typeof value === 'number' ? value : 0;
  return castedValue;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

// make sure that full resolution jobs don't cache improperly to signal success
// when they have failed earlier

function foo(value: Indirect<string> | number): Indirect<string> | number {
  const castedValue: number = typeof value === "number" ? value : 0;
  return castedValue;
}

`;
